package controller

import (
	"061/Sgame/constant"
	"061/Sgame/db"
	"061/Sgame/net"
	"061/Sgame/server/login/model"
	"061/Sgame/server/login/proto"
	"061/Sgame/server/models"
	"061/Sgame/utils"
	"fmt"
	"github.com/mitchellh/mapstructure"
	"log"
	"time"
)

var DefaultAccount = &Account{}

type Account struct {
}

// Router 来一个消息{"name":"account.login"}  Account相当于一个组。现在添加一条login路由标识
func (a *Account) Router(r *net.Router) {
	g := r.Group("account")
	g.AddRouter("login", a.login)   //相当于map[login]a.login
	g.AddRouter("logout", a.logout) //登出游戏
}

//路由group组下handleMap（结构为map[string]HandleFunc），login的处理函数HandleFunc
func (a *Account) login(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
	/**
		1. 用户名 密码 硬件id
		2. 根据用户名 查询user表 得到数据
		3. 进行密码比对，如果密码正确 登录成功
	    4. 保存用户登录记录
		5. 保存用户的最后一次登录信息
	    6. 客户端 需要 一个session，jwt 生成一个加密字符串的加密算法
	    7. 客户端 在发起需要用户登录的行为时，判断用户是否合法
	*/
	loginReq := &proto.LoginReq{}
	loginRes := &proto.LoginRsp{}
	err := mapstructure.Decode(req.Body.Msg, loginReq)
	if err != nil {
		fmt.Println(err)
		return
	}
	var user models.User
	err = db.GormDB.Where("username=?", loginReq.Username).First(&user).Error
	if err != nil {
		log.Println("用户表查询出错", err)
		rsp.Body.Code = constant.UserNotExist
		return
	}
	//验证密码是否正确
	pwd := utils.Password(loginReq.Password, user.Passcode)
	if pwd != user.Passwd {
		rsp.Body.Code = constant.PwdIncorrect
		return
	}
	token, _ := utils.Award(user.UId)
	rsp.Body.Code = constant.OK
	loginRes.UId = user.UId
	loginRes.Username = user.Username
	loginRes.Session = token
	loginRes.Password = ""
	rsp.Body.Msg = loginRes
	//保存用户登录记录 保存到LoginHistory表中
	loginHistory := &model.LoginHistory{
		UId: user.UId, CTime: time.Now(), Ip: loginReq.Ip,
		Hardware: loginReq.Hardware, State: model.Login,
	}
	err = db.GormDB.Create(&loginHistory).Error
	if err != nil {
		log.Println("保存用户登录记录失败:", err)
		return
	}
	//最后一次登录的状态记录
	loginLast := &model.LoginLast{}
	err = db.GormDB.Where("uid=?", user.UId).First(&loginLast).Error
	if err != nil {
		//没历史记录 创建
		loginLast.IsLogout = 0
		loginLast.Ip = loginReq.Ip
		loginLast.LoginTime = time.Now()
		loginLast.Session = token
		loginLast.Hardware = loginReq.Hardware
		loginLast.UId = user.UId
		err = db.GormDB.Create(&loginLast).Error
		if err != nil {
			log.Println("最后一次登录的状态记录创建失败:", err)
		}
	} else {
		//有数据 更新
		loginLast.IsLogout = 0
		loginLast.Ip = loginReq.Ip
		loginLast.LoginTime = time.Now()
		loginLast.Session = token
		loginLast.Hardware = loginReq.Hardware
		err = db.GormDB.Updates(loginLast).Error
		if err != nil {
			log.Println("最后一次登录的状态记录更新失败:", err)
		}

	}
	//缓存一下 此用户和当前的ws连接
	net.Mgr.UserLogin(req.Conn, user.UId, token)
}

func (a *Account) logout(req *net.WsMsgReq, rsp *net.WsMsgRsp) {

	reqObj := &proto.LogoutReq{}
	rspObj := &proto.LogoutRsp{}
	mapstructure.Decode(req.Body.Msg, reqObj)
	rsp.Body.Msg = rspObj
	rspObj.UId = reqObj.UId
	rsp.Body.Code = constant.OK

	tt := time.Now()
	//登出，写记录
	loginHistory := &model.LoginHistory{UId: reqObj.UId, CTime: tt, State: model.Logout}
	err := db.GormDB.Create(&loginHistory).Error
	if err != nil {
		log.Println("保存用户登出记录失败:", err)
		return
	}
	loginLast := &model.LoginLast{}
	err = db.GormDB.Where("uid=?", reqObj.UId).First(&loginLast).Error
	if err != nil {
		//没历史记录 创建
		loginLast = &model.LoginLast{UId: reqObj.UId, LogoutTime: tt, IsLogout: 0}
		err = db.GormDB.Create(&loginLast).Error
		if err != nil {
			log.Println("最后一次登出的状态记录创建失败:", err)
		}
	} else {
		//有数据 更新
		loginLast.IsLogout = 1
		loginLast.LogoutTime = time.Now()
		err = db.GormDB.Model(&loginLast).Updates(loginLast).Error
		if err != nil {
			log.Println("最后一次登出的状态记录更新失败:", err)
		}
	}

	net.Mgr.UserLogout(req.Conn)
}
